package main.java;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;

public class RawObservation {

	private String rawObservation;
	private HashMap<String,String> properties = new HashMap<String,String>();
	private double x, y, z;

	private String name;

	// For testing the values of the example
	private String setupID = "TPSSetupID_23";
	private boolean directFace = true;
	private String purpose = "normal";
	private String tpsCorrection = "6";

	private String timeStamp;

	private double targetHeight;
	private double horizAngle;
	private double zenithAngle;
	private double horizDistance;
	private double slopeDistance;

	private boolean coordinateSet;

	public RawObservation()
	{
		setTimeStamp(new Date());
		coordinateSet = false;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	/*
	 * SETTER AND GETTER FOR TARGET POINT COORDINATES
	 */
	public void setXValue(double x) {
		this.x = x;
		coordinateSet = true;
	}

	public void setYValue(double y) {
		this.y = y;
		coordinateSet = true;
	}

	public void setZValue(double z) {
		this.z = z;
		coordinateSet = true;
	}

	public double getXValue() {
		return x;
	}

	public double getYValue() {
		return y;
	}

	public double getZValue() {
		return z;
	}

	public String getSetupID() {
		return setupID;
	}

	public void setSetupID(String setupID) {
		this.setupID = setupID;
	}

	public boolean isDirectFace() {
		return directFace;
	}

	public void setDirectFace(boolean directFace) {
		this.directFace = directFace;
	}

	public String getPurpose() {
		return purpose;
	}

	public void setPurpose(String purpose) {
		this.purpose = purpose;
	}

	public double getTargetHeight() {
		return targetHeight;
	}

	public void setTargetHeight(double targetHeight) {
		this.targetHeight = targetHeight;
	}

	public void setTargetHeight(String th) {
		this.targetHeight = Double.parseDouble(th);
	}

	public double getHorizAngle() {
		return horizAngle;
	}

	public void setHorizAngle(double horizAngle) {
		this.horizAngle = horizAngle;
	}

	public double getZenithAngle() {
		return zenithAngle;
	}

	public void setZenithAngle(double zenithAngle) {
		this.zenithAngle = zenithAngle;
	}

	public double getHorizDistance() {
		return horizDistance;
	}

	public void setHorizDistance(double horizDistance) {
		this.horizDistance = horizDistance;
	}

	public void setHorizDistance(String hd) {
		this.horizDistance = Double.parseDouble(hd);
	}

	public double getSlopeDistance() {
		return slopeDistance;
	}

	public void setSlopeDistance(double slopeDistance) {
		this.slopeDistance = slopeDistance;
	}

	public String getTpsCorrection() {
		return tpsCorrection;
	}

	public void setTpsCorrection(String tpsCorrection) {
		this.tpsCorrection = tpsCorrection;
	}

	public String getTimeStamp() {
		return timeStamp;
	}

	public void setTimeStamp(String timeStamp) {
		this.timeStamp = timeStamp;
	}

	public void setTimeStamp(Date timeStamp)
	{
		SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
		this.timeStamp = date.format(timeStamp) + "T" + time.format(timeStamp);
	}

	public void addProperty(String label, String value) {
		if (label.equals("targetHeight")) {
			this.setTargetHeight(value);
		} else if (label.equals("horizDistance")) {
			this.setHorizDistance(value);
		} else {
			properties.put(label, value);
		}
	}

	public String getRawObservation()
	{
		calculateHorizDistances();

		DecimalFormatSymbols otherSeperators = new DecimalFormatSymbols(Locale.GERMAN);
		otherSeperators.setDecimalSeparator('.');
		otherSeperators.setGroupingSeparator(','); 
		DecimalFormat df = new DecimalFormat("0.000000", otherSeperators);
		DecimalFormat df2 = new DecimalFormat("0.000000000000", otherSeperators);

		rawObservation = "<RawObservation setupID=\"" + setupID + "\" purpose=\""+ purpose + "\" targetHeight=\"" + df.format(targetHeight) + "\" horizAngle=\""
				+ df2.format(horizAngle) + "\" zenithAngle=\"" + df2.format(zenithAngle) + "\"";
		String out = "";
		if (coordinateSet) {
			out += rawObservation + " horizDistance=\"" + df.format(horizDistance) + "\" slopeDistance=\"" + df.format(slopeDistance) + "\" directFace=\""+ directFace + "\" timeStamp=\"" + timeStamp + "\">\n";
			out += "<TargetPoint name=\"" + name + "\" pntRef=\"" + name +"\">" + df.format(x) + " " + df.format(y) + " " + df.format(z) + "</TargetPoint>\n";
		} else {
			out += rawObservation + " directFace=\""+ directFace + "\" timeStamp=\"" + timeStamp + "\">\n";
			out += "<TargetPoint name=\"" + name + "\"/>\n";
		}
		if (!properties.isEmpty()) {
			out += "<Feature code=\"observationInfo\">\n";
			out += "<Property label=\"TPSCorrectionRef\" value=\""+ tpsCorrection + "\"/>\n";
			Set<String> labels = properties.keySet();
			for(String label : labels) {
				out += "<Property label=\"" + label + "\" value=\"" + properties.get(label) + "\"/>\n";
			}
			out += "</Feature>\n";
		}
		out += "</RawObservation>";

		return out;
	}

	private void calculateHorizDistances()
	{
		this.setHorizDistance(Math.sqrt(Math.pow(getXValue(), 2) + Math.pow(getYValue(), 2)));
	}
}
